package com.lijiajia.cloud.common.security.oauth2.token.provider;


import com.lijiajia.cloud.common.core.Constants;
import com.lijiajia.cloud.common.security.user.ICloudUser;
import com.lijiajia.cloud.common.security.user.DefaultCloudUser;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.oauth2.provider.token.UserAuthenticationConverter;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * CustomUserAuthenticationConverter
 *
 * @author lijiajia
 * @since 2019-04-12
 */
public class CloudUserAuthenticationConverter implements UserAuthenticationConverter {
	protected final String USER = "user";

	/**
	 * 用户默认角色
	 */
	private Collection<? extends GrantedAuthority> defaultAuthorities;

	@Override
	public Map<String, ?> convertUserAuthentication(Authentication authentication) {
		Map<String, Object> response = new LinkedHashMap<>();
		Object principal = authentication.getPrincipal();
		if (principal instanceof ICloudUser) {
			ICloudUser userDetails = (ICloudUser) principal;
			response.put(USER, convertCloudUser(userDetails));
		}

		if (authentication.getAuthorities() != null && !authentication.getAuthorities().isEmpty()) {
			response.put(AUTHORITIES, AuthorityUtils.authorityListToSet(authentication.getAuthorities()));
		}
		return response;
	}

	@Override
	public Authentication extractAuthentication(Map<String, ?> map) {
		if (map.containsKey(USER)) {
			Object user = map.get(USER);
			ICloudUser principal = extractCloudUser(user);
			Collection<? extends GrantedAuthority> authorities = getAuthorities(map);
			return new UsernamePasswordAuthenticationToken(principal, "N/A", authorities);
		}
		return null;
	}

	private Collection<? extends GrantedAuthority> getAuthorities(Map<String, ?> map) {
		if (!map.containsKey(AUTHORITIES)) {
			return defaultAuthorities;
		}
		Object authorities = map.get(AUTHORITIES);
		if (authorities instanceof String) {
			return AuthorityUtils.commaSeparatedStringToAuthorityList((String) authorities);
		}
		if (authorities instanceof Collection) {
			return AuthorityUtils.commaSeparatedStringToAuthorityList(StringUtils
				.collectionToCommaDelimitedString((Collection<?>) authorities));
		}
		throw new IllegalArgumentException("Authorities must be either a String or a Collection");
	}

	/**
	 * 如果用户没有设置角色 则为权限的默认值
	 *
	 * @param defaultAuthorities 设置默认权限, 默认为null
	 */
	public void setDefaultAuthorities(String[] defaultAuthorities) {
		this.defaultAuthorities = AuthorityUtils.commaSeparatedStringToAuthorityList(StringUtils
			.arrayToCommaDelimitedString(defaultAuthorities));
	}

	/**
	 * 转换 user 对象
	 *
	 * @param user user
	 * @return map类型格式
	 */
	private Map<String, ?> convertCloudUser(ICloudUser user) {
		Map<String, String> userMap = new HashMap<>();
		userMap.put(ICloudUser.USER_ID, user.getUserId());
		userMap.put(ICloudUser.LOGIN_NAME, user.getLoginName());
		userMap.put(ICloudUser.TELEPHONE, user.getTelephone());
		userMap.put(ICloudUser.EMAIL, user.getEmail());
		userMap.put(ICloudUser.AVATAR, user.getAvatar());
		userMap.put(ICloudUser.REAL_NAME, user.getRealName());
		if (user.getEnabled() != null) {
			userMap.put(ICloudUser.ENABLED, user.getEnabled().toString());
		}
		if (user.getJoinTime() != null){
			userMap.put(ICloudUser.JOIN_TIME, user.getJoinTime().format(Constants.DEFAULT_DATE_TIME_FORMATTER));
		}

		return userMap;
	}

	/**
	 * 解析 user 对象格式
	 *
	 * @param userObj user对象
	 * @return
	 */
	private ICloudUser extractCloudUser(Object userObj) {
		if (userObj instanceof Map) {
			@SuppressWarnings("unchecked")
			Map<String, String> userMap = (Map<String, String>) userObj;
			DefaultCloudUser user = new DefaultCloudUser();
			user.setUserId(userMap.get(ICloudUser.USER_ID))
				.setLoginName(userMap.get(ICloudUser.LOGIN_NAME))
				.setTelephone(userMap.get(ICloudUser.TELEPHONE))
				.setEmail(userMap.get(ICloudUser.EMAIL))
				.setRealName(userMap.get(ICloudUser.REAL_NAME))
				.setAvatar(userMap.get(ICloudUser.AVATAR))
				.setEnabled(Boolean.valueOf(userMap.get(ICloudUser.ENABLED)))
				.setJoinTime(LocalDateTime.parse(
					userMap.get(ICloudUser.JOIN_TIME),
					Constants.DEFAULT_DATE_TIME_FORMATTER));
			return user;
		}
		return null;
	}
}
